package cn.com.nwpu.visual_system.service.impl;

import cn.com.nwpu.visual_system.entity.AllSensorData;
import cn.com.nwpu.visual_system.entity.ConfigData;
import cn.com.nwpu.visual_system.entity.ModelPredictData;
import cn.com.nwpu.visual_system.mapper.ConfigDataMapper;
import cn.com.nwpu.visual_system.mapper.ModelPredictDataMapper;
import cn.com.nwpu.visual_system.mapper.TestDataMapper;
import cn.com.nwpu.visual_system.service.ModelService;
import cn.com.nwpu.visual_system.tool.ExecutePython;
import cn.com.nwpu.visual_system.tool.GetUrl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Hutengzhong
 * @version 1.0.0
 * @title ModelServiceImpl
 * @description TODO
 * @date 2024/5/18 17:03
 */
@Service
public class ModelServiceImpl implements ModelService {
    @Autowired
    ModelPredictDataMapper modelPredictDataMapper;
    @Autowired
    TestDataMapper testDataMapper;
    @Autowired
    ConfigDataMapper configDataMapper;
    @Value("${init-config.value-name}")
    String valueName;

    /**
     * 模型训练，得到p、v矩阵和t2、sp阈值，并写入文件做持久化存储
     * 只训练了正常情况下的阈值情况，故障将通过是否偏离阈值判断
     */
    @Override
    public void trainModel() {
        ExecutePython executePython = new ExecutePython();
        executePython.train();
    }

    /**
     * 预测当前时间点获得的信息是否正常，数据从数据库中读取
     *
     * @return 预测的T2和SPE值
     */
    @Override
    public ModelPredictData predictModel() {
        // 获取当前数据的最新值
        ConfigData configData = configDataMapper.getCurrentTestDataId();
        Integer testDataId = Integer.parseInt(configData.getConfigValue());


        AllSensorData allSensorData = testDataMapper.getAllSensorData(testDataId);

        // 更新当前的测试数据id，其他地方的数据更新全部在这里处理
        Integer count = configDataMapper.updateTestDataId(testDataId + 1);
        ExecutePython executePython = new ExecutePython();
        ModelPredictData modelPredictData = executePython.predict(allSensorData.toString());
        // 将预测结果保存
        int result = modelPredictDataMapper.insertPredictData(modelPredictData);
        return modelPredictData;
    }

    @Override
    public Map<String, String> getStandard() {
        // TODO 返回标准的两个阈值，标准的两个阈值直接从txt文件读取，不再单独走数据库
        GetUrl getUrl = new GetUrl();
        String valuePath = getUrl.getValuePath(valueName);
        String standardT2 = "";
        String standardSPE = "";
        try (BufferedReader reader = new BufferedReader(new FileReader(valuePath))) {
            standardT2 = reader.readLine();
            standardSPE = reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("standardT2", standardT2);
        returnMap.put("standardSPE", standardSPE);
        return returnMap;
    }

    /**
     * 每次获取100条预测的数据，当数据不足时，用空值填充
     *
     * @return
     */
    @Override
    public Map<String, List<Object>> getPredictMap() {
        // 获取当前已经计算了的诊断值
        ConfigData configData = configDataMapper.getCurrentTestDataId();
        Integer testDataId = Integer.parseInt(configData.getConfigValue());
        // 读取最近的100条诊断数据情况
        List<ModelPredictData> modelPredictDataList = modelPredictDataMapper.getPredictList(testDataId >= 100 ? testDataId - 100 : 0);
        List<Integer> modelPredictIdList = modelPredictDataList
                .stream()
                .map(ModelPredictData::getModelPredictId)
                .collect(Collectors.toList());
        List<LocalDateTime> insertTimeList = modelPredictDataList
                .stream()
                .map(ModelPredictData::getInsertTime)
                .collect(Collectors.toList());
        List<String> TValueList = modelPredictDataList
                .stream()
                .map(ModelPredictData::getTValue)
                .collect(Collectors.toList());
        List<String> SPEValueList = modelPredictDataList
                .stream()
                .map(ModelPredictData::getSPE)
                .collect(Collectors.toList());
        Map resultMap = new HashMap();
        resultMap.put("predictId", modelPredictIdList);
        resultMap.put("insertTime", insertTimeList);
        resultMap.put("TValue", TValueList);
        resultMap.put("SPE", SPEValueList);
//        System.out.println(modelPredictDataList.size());
        // 获取新诊断值时已经更新了id，所有这里不再做更新id的操作
        return resultMap;
    }
}
